home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tar.gnu / sprite / RCS / rtape_lib.c,v < prev    next >
Encoding:
Text File  |  1992-03-29  |  13.0 KB  |  702 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     92.03.28.17.32.35;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     90.06.28.15.34.58;  author rab;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     90.03.21.21.54.41;  author rab;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @@
  27.  
  28.  
  29. 1.3
  30. log
  31. @Lint.
  32. @
  33. text
  34. @/* Remote tape emulator subroutines.
  35.    Copyright (C) 1988 Free Software Foundation
  36.  
  37. This file is part of GNU Tar.
  38.  
  39. GNU Tar is free software; you can redistribute it and/or modify
  40. it under the terms of the GNU General Public License as published by
  41. the Free Software Foundation; either version 1, or (at your option)
  42. any later version.
  43.  
  44. GNU Tar is distributed in the hope that it will be useful,
  45. but WITHOUT ANY WARRANTY; without even the implied warranty of
  46. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  47. GNU General Public License for more details.
  48.  
  49. You should have received a copy of the GNU General Public License
  50. along with GNU Tar; see the file COPYING.  If not, write to
  51. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  52.  
  53. /* JF: modified to make all rmtXXX calls into macros for speed */
  54.  
  55. #ifndef lint
  56. static char *RCSid = "$Header: /sprite/src/cmds/tar.gnu/sprite/RCS/rtape_lib.c,v 1.2 90/06/28 15:34:58 rab Exp Locker: kupfer $";
  57. #endif
  58.  
  59. /*
  60.  * $Log:    rtape_lib.c,v $
  61.  * Revision 1.2  90/06/28  15:34:58  rab
  62.  * Added support for long filenames and long symbolic linkes.
  63.  * 
  64.  * Revision 1.1  90/03/21  21:54:41  rab
  65.  * Initial revision
  66.  * 
  67.  * Revision 1.7  89/03/23  14:09:51  root
  68.  * Fix from haynes@@ucscc.ucsc.edu for use w/compat. ADR.
  69.  * 
  70.  * Revision 1.6  88/10/25  17:04:29  root
  71.  * rexec code and a bug fix from srs!dan, miscellanious cleanup. ADR.
  72.  * 
  73.  * Revision 1.5  88/10/25  16:30:17  root
  74.  * Fix from jeff@@gatech.edu for getting user@@host:dev right. ADR.
  75.  * 
  76.  * Revision 1.4  87/10/30  10:36:12  root
  77.  * Made 4.2 syntax a compile time option. ADR.
  78.  * 
  79.  * Revision 1.3  87/04/22  11:16:48  root
  80.  * Two fixes from parmelee@@wayback.cs.cornell.edu to correctly
  81.  * do fd biasing and rmt protocol on 'S' command. ADR.
  82.  * 
  83.  * Revision 1.2  86/10/09  16:38:53  root
  84.  * Changed to reflect 4.3BSD rcp syntax. ADR.
  85.  * 
  86.  * Revision 1.1  86/10/09  16:17:35  root
  87.  * Initial revision
  88.  * 
  89.  */
  90.  
  91. /*
  92.  *    rmt --- remote tape emulator subroutines
  93.  *
  94.  *    Originally written by Jeff Lee, modified some by Arnold Robbins
  95.  *
  96.  *    WARNING:  The man page rmt(8) for /etc/rmt documents the remote mag
  97.  *    tape protocol which rdump and rrestore use.  Unfortunately, the man
  98.  *    page is *WRONG*.  The author of the routines I'm including originally
  99.  *    wrote his code just based on the man page, and it didn't work, so he
  100.  *    went to the rdump source to figure out why.  The only thing he had to
  101.  *    change was to check for the 'F' return code in addition to the 'E',
  102.  *    and to separate the various arguments with \n instead of a space.  I
  103.  *    personally don't think that this is much of a problem, but I wanted to
  104.  *    point it out.
  105.  *    -- Arnold Robbins
  106.  *
  107.  *    Redone as a library that can replace open, read, write, etc, by
  108.  *    Fred Fish, with some additional work by Arnold Robbins.
  109.  */
  110.  
  111. /*
  112.  *    MAXUNIT --- Maximum number of remote tape file units
  113.  *
  114.  *    READ --- Return the number of the read side file descriptor
  115.  *    WRITE --- Return the number of the write side file descriptor
  116.  */
  117.  
  118. /* #define RMTIOCTL    1 */
  119. /* #define USE_REXEC    1    /* rexec code courtesy of Dan Kegel, srs!dan */
  120.  
  121. #include <stdio.h>
  122. #include <signal.h>
  123. #include <sys/types.h>
  124.  
  125. #ifdef RMTIOCTL
  126. #include <sys/ioctl.h>
  127. #include <sys/mtio.h>
  128. #endif
  129.  
  130. #ifdef USE_REXEC
  131. #include <netdb.h>
  132. #endif
  133.  
  134. #include <errno.h>
  135. #include <setjmp.h>
  136. #include <sys/stat.h>
  137.  
  138. #define BUFMAGIC    64    /* a magic number for buffer sizes */
  139. #define MAXUNIT    4
  140.  
  141. #define READ(fd)    (Ctp[fd][0])
  142. #define WRITE(fd)    (Ptc[fd][1])
  143.  
  144. static int Ctp[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  145. static int Ptc[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  146.  
  147. extern int errno;
  148.  
  149. char *__rmt_path;
  150.  
  151. /*
  152.  *    _rmt_panic --- close off a remote tape connection
  153.  */
  154.  
  155. static void _rmt_panic(fildes)
  156. int fildes;
  157. {
  158.     close(READ(fildes));
  159.     close(WRITE(fildes));
  160.     READ(fildes) = -1;
  161.     WRITE(fildes) = -1;
  162. }
  163.  
  164.  
  165.  
  166. /*
  167.  *    command --- attempt to perform a remote tape command
  168.  */
  169.  
  170. static int command(fildes, buf)
  171. int fildes;
  172. char *buf;
  173. {
  174.     register int blen;
  175. #ifdef USG
  176.     void (*pstat)();
  177. #else
  178.     int (*pstat)();
  179. #endif
  180.  
  181. /*
  182.  *    save current pipe status and try to make the request
  183.  */
  184.  
  185.     blen = strlen(buf);
  186.     pstat = (int (*)()) signal(SIGPIPE, SIG_IGN);
  187.     if (write(WRITE(fildes), buf, blen) == blen)
  188.     {
  189.         signal(SIGPIPE, pstat);
  190.         return(0);
  191.     }
  192.  
  193. /*
  194.  *    something went wrong. close down and go home
  195.  */
  196.  
  197.     signal(SIGPIPE, pstat);
  198.     _rmt_panic(fildes);
  199.  
  200.     errno = EIO;
  201.     return(-1);
  202. }
  203.  
  204.  
  205.  
  206. /*
  207.  *    status --- retrieve the status from the pipe
  208.  */
  209.  
  210. static int status(fildes)
  211. int fildes;
  212. {
  213.     int i;
  214.     char c, *cp;
  215.     char buffer[BUFMAGIC];
  216.  
  217. /*
  218.  *    read the reply command line
  219.  */
  220.  
  221.     for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++)
  222.     {
  223.         if (read(READ(fildes), cp, 1) != 1)
  224.         {
  225.             _rmt_panic(fildes);
  226.             errno = EIO;
  227.             return(-1);
  228.         }
  229.         if (*cp == '\n')
  230.         {
  231.             *cp = 0;
  232.             break;
  233.         }
  234.     }
  235.  
  236.     if (i == BUFMAGIC)
  237.     {
  238.         _rmt_panic(fildes);
  239.         errno = EIO;
  240.         return(-1);
  241.     }
  242.  
  243. /*
  244.  *    check the return status
  245.  */
  246.  
  247.     for (cp = buffer; *cp; cp++)
  248.         if (*cp != ' ')
  249.             break;
  250.  
  251.     if (*cp == 'E' || *cp == 'F')
  252.     {
  253.         errno = atoi(cp + 1);
  254.         while (read(READ(fildes), &c, 1) == 1)
  255.             if (c == '\n')
  256.                 break;
  257.  
  258.         if (*cp == 'F')
  259.             _rmt_panic(fildes);
  260.  
  261.         return(-1);
  262.     }
  263.  
  264. /*
  265.  *    check for mis-synced pipes
  266.  */
  267.  
  268.     if (*cp != 'A')
  269.     {
  270.         _rmt_panic(fildes);
  271.         errno = EIO;
  272.         return(-1);
  273.     }
  274.  
  275.     return(atoi(cp + 1));
  276. }
  277.  
  278. #ifdef USE_REXEC
  279.  
  280. /*
  281.  * _rmt_rexec
  282.  *
  283.  * execute /etc/rmt on a remote system using rexec().
  284.  * Return file descriptor of bidirectional socket for stdin and stdout
  285.  * If username is NULL, or an empty string, uses current username.
  286.  *
  287.  * ADR: By default, this code is not used, since it requires that
  288.  * the user have a .netrc file in his/her home directory, or that the
  289.  * application designer be willing to have rexec prompt for login and
  290.  * password info. This may be unacceptable, and .rhosts files for use
  291.  * with rsh are much more common on BSD systems.
  292.  */
  293.  
  294. static int
  295. _rmt_rexec(host, user)
  296. char *host;
  297. char *user;        /* may be NULL */
  298. {
  299.     struct servent *rexecserv;
  300.  
  301.     rexecserv = getservbyname("exec", "tcp");
  302.     if (NULL == rexecserv) {
  303.         fprintf (stderr, "? exec/tcp: service not available.");
  304.         exit (-1);
  305.     }
  306.     if ((user != NULL) && *user == '\0')
  307.         user = (char *) NULL;
  308.     return rexec (&host, rexecserv->s_port, user, NULL,
  309.             "/etc/rmt", (int *)NULL);
  310. }
  311. #endif /* USE_REXEC */
  312.  
  313. /*
  314.  *    _rmt_open --- open a magtape device on system specified, as given user
  315.  *
  316.  *    file name has the form [user@@]system:/dev/????
  317. #ifdef COMPAT
  318.  *    file name has the form system[.user]:/dev/????
  319. #endif
  320.  */
  321.  
  322. #define MAXHOSTLEN    257    /* BSD allows very long host names... */
  323.  
  324. int __rmt_open (path, oflag, mode, bias)
  325. char *path;
  326. int oflag;
  327. int mode;
  328. int bias;
  329. {
  330.     int i, rc;
  331.     char buffer[BUFMAGIC];
  332.     char system[MAXHOSTLEN];
  333.     char device[BUFMAGIC];
  334.     char login[BUFMAGIC];
  335.     char *sys, *dev, *user;
  336.  
  337.     sys = system;
  338.     dev = device;
  339.     user = login;
  340.  
  341. /*
  342.  *    first, find an open pair of file descriptors
  343.  */
  344.  
  345.     for (i = 0; i < MAXUNIT; i++)
  346.         if (READ(i) == -1 && WRITE(i) == -1)
  347.             break;
  348.  
  349.     if (i == MAXUNIT)
  350.     {
  351.         errno = EMFILE;
  352.         return(-1);
  353.     }
  354.  
  355. /*
  356.  *    pull apart system and device, and optional user
  357.  *    don't munge original string
  358.  *    if COMPAT is defined, also handle old (4.2) style person.site notation.
  359.  */
  360.  
  361.     while (*path != '@@'
  362. #ifdef COMPAT
  363.             && *path != '.'
  364. #endif
  365.             && *path != ':') {
  366.         *sys++ = *path++;
  367.     }
  368.     *sys = '\0';
  369.     path++;
  370.  
  371.     if (*(path - 1) == '@@')
  372.     {
  373.         (void) strcpy (user, system);    /* saw user part of user@@host */
  374.         sys = system;            /* start over */
  375.         while (*path != ':') {
  376.             *sys++ = *path++;
  377.         }
  378.         *sys = '\0';
  379.         path++;
  380.     }
  381. #ifdef COMPAT
  382.     else if (*(path - 1) == '.')
  383.     {
  384.         while (*path != ':') {
  385.             *user++ = *path++;
  386.         }
  387.         *user = '\0';
  388.         path++;
  389.     }
  390. #endif
  391.     else
  392.         *user = '\0';
  393.  
  394.     while (*path) {
  395.         *dev++ = *path++;
  396.     }
  397.     *dev = '\0';
  398.  
  399. #ifdef USE_REXEC
  400. /* 
  401.  *    Execute the remote command using rexec 
  402.  */
  403.     READ(i) = WRITE(i) = _rmt_rexec(system, login);
  404.     if (READ(i) < 0)
  405.         return -1;
  406. #else
  407. /*
  408.  *    setup the pipes for the 'rsh' command and fork
  409.  */
  410.  
  411.     if (pipe(Ptc[i]) == -1 || pipe(Ctp[i]) == -1)
  412.         return(-1);
  413.  
  414.     if ((rc = fork()) == -1)
  415.         return(-1);
  416.  
  417.     if (rc == 0)
  418.     {
  419.         close(0);
  420.         dup(Ptc[i][0]);
  421.         close(Ptc[i][0]); close(Ptc[i][1]);
  422.         close(1);
  423.         dup(Ctp[i][1]);
  424.         close(Ctp[i][0]); close(Ctp[i][1]);
  425.         (void) setuid (getuid ());
  426.         (void) setgid (getgid ());
  427.         if (*login)
  428.         {
  429.             execl("/usr/ucb/rsh", "rsh", system, "-l", login,
  430.                 "/etc/rmt", (char *) 0);
  431.             execl("/usr/bin/remsh", "remsh", system, "-l", login,
  432.                 "/etc/rmt", (char *) 0);
  433.             execl("/usr/bin/rsh", "rsh", system, "-l", login,
  434.                 "/etc/rmt", (char *) 0);
  435.             execl("/usr/bsd/rsh", "rsh", system, "-l", login,
  436.                 "/etc/rmt", (char *)0);
  437.         }
  438.         else
  439.         {
  440.             execl("/usr/ucb/rsh", "rsh", system,
  441.                 "/etc/rmt", (char *) 0);
  442.             execl("/usr/bin/remsh", "remsh", system,
  443.                 "/etc/rmt", (char *) 0);
  444.             execl("/usr/bin/rsh", "rsh", system,
  445.                 "/etc/rmt", (char *) 0);
  446.             execl("/usr/bsd/rsh", "rsh", system,
  447.                 "/etc/rmt", (char *) 0);
  448.         }
  449.  
  450. /*
  451.  *    bad problems if we get here
  452.  */
  453.  
  454.         perror("remote shell exec");
  455.         exit(1);
  456.     }
  457.  
  458.     close(Ptc[i][0]); close(Ctp[i][1]);
  459. #endif
  460.  
  461. /*
  462.  *    now attempt to open the tape device
  463.  */
  464.  
  465.     sprintf(buffer, "O%s\n%d\n", device, oflag);
  466.     if (command(i, buffer) == -1 || status(i) == -1)
  467.         return(-1);
  468.  
  469.     return(i+bias);
  470. }
  471.  
  472.  
  473.  
  474. /*
  475.  *    _rmt_close --- close a remote magtape unit and shut down
  476.  */
  477.  
  478.  int __rmt_close(fildes)
  479. int fildes;
  480. {
  481.     int rc;
  482.  
  483.     if (command(fildes, "C\n") != -1)
  484.     {
  485.         rc = status(fildes);
  486.  
  487.         _rmt_panic(fildes);
  488.         return(rc);
  489.     }
  490.  
  491.     return(-1);
  492. }
  493.  
  494.  
  495.  
  496. /*
  497.  *    _rmt_read --- read a buffer from a remote tape
  498.  */
  499.  
  500. int __rmt_read(fildes, buf, nbyte)
  501. int fildes;
  502. char *buf;
  503. int nbyte;
  504. {
  505.     int rc, i;
  506.     char buffer[BUFMAGIC];
  507.  
  508.     sprintf(buffer, "R%d\n", nbyte);
  509.     if (command(fildes, buffer) == -1 || (rc = status(fildes)) == -1)
  510.         return(-1);
  511.  
  512.     for (i = 0; i < rc; i += nbyte, buf += nbyte)
  513.     {
  514.         nbyte = read(READ(fildes), buf, rc);
  515.         if (nbyte <= 0)
  516.         {
  517.             _rmt_panic(fildes);
  518.             errno = EIO;
  519.             return(-1);
  520.         }
  521.     }
  522.  
  523.     return(rc);
  524. }
  525.  
  526.  
  527.  
  528. /*
  529.  *    _rmt_write --- write a buffer to the remote tape
  530.  */
  531.  
  532. int __rmt_write(fildes, buf, nbyte)
  533. int fildes;
  534. char *buf;
  535. unsigned int nbyte;
  536. {
  537.     char buffer[BUFMAGIC];
  538. #ifdef USG
  539.     void (*pstat)();
  540. #else
  541.     int (*pstat)();
  542. #endif
  543.  
  544.     sprintf(buffer, "W%d\n", nbyte);
  545.     if (command(fildes, buffer) == -1)
  546.         return(-1);
  547.  
  548.     pstat = (int (*)()) signal(SIGPIPE, SIG_IGN);
  549.     if (write(WRITE(fildes), buf, nbyte) == nbyte)
  550.     {
  551.         signal (SIGPIPE, pstat);
  552.         return(status(fildes));
  553.     }
  554.  
  555.     signal (SIGPIPE, pstat);
  556.     _rmt_panic(fildes);
  557.     errno = EIO;
  558.     return(-1);
  559. }
  560.  
  561.  
  562.  
  563. /*
  564.  *    _rmt_lseek --- perform an imitation lseek operation remotely
  565.  */
  566.  
  567. long __rmt_lseek(fildes, offset, whence)
  568. int fildes;
  569. long offset;
  570. int whence;
  571. {
  572.     char buffer[BUFMAGIC];
  573.  
  574.     sprintf(buffer, "L%d\n%d\n", offset, whence);
  575.     if (command(fildes, buffer) == -1)
  576.         return(-1);
  577.  
  578.     return(status(fildes));
  579. }
  580.  
  581.  
  582. /*
  583.  *    _rmt_ioctl --- perform raw tape operations remotely
  584.  */
  585.  
  586. #ifdef RMTIOCTL
  587. __rmt_ioctl(fildes, op, arg)
  588. int fildes, op;
  589. char *arg;
  590. {
  591.     char c;
  592.     int rc, cnt;
  593.     char buffer[BUFMAGIC];
  594.  
  595. /*
  596.  *    MTIOCOP is the easy one. nothing is transfered in binary
  597.  */
  598.  
  599.     if (op == MTIOCTOP)
  600.     {
  601.         sprintf(buffer, "I%d\n%d\n", ((struct mtop *) arg)->mt_op,
  602.             ((struct mtop *) arg)->mt_count);
  603.         if (command(fildes, buffer) == -1)
  604.             return(-1);
  605.         return(status(fildes));
  606.     }
  607.  
  608. /*
  609.  *    we can only handle 2 ops, if not the other one, punt
  610.  */
  611.  
  612.     if (op != MTIOCGET)
  613.     {
  614.         errno = EINVAL;
  615.         return(-1);
  616.     }
  617.  
  618. /*
  619.  *    grab the status and read it directly into the structure
  620.  *    this assumes that the status buffer is (hopefully) not
  621.  *    padded and that 2 shorts fit in a long without any word
  622.  *    alignment problems, ie - the whole struct is contiguous
  623.  *    NOTE - this is probably NOT a good assumption.
  624.  */
  625.  
  626.     if (command(fildes, "S") == -1 || (rc = status(fildes)) == -1)
  627.         return(-1);
  628.  
  629.     for (; rc > 0; rc -= cnt, arg += cnt)
  630.     {
  631.         cnt = read(READ(fildes), arg, rc);
  632.         if (cnt <= 0)
  633.         {
  634.             _rmt_panic(fildes);
  635.             errno = EIO;
  636.             return(-1);
  637.         }
  638.     }
  639.  
  640. /*
  641.  *    now we check for byte position. mt_type is a small integer field
  642.  *    (normally) so we will check its magnitude. if it is larger than
  643.  *    256, we will assume that the bytes are swapped and go through
  644.  *    and reverse all the bytes
  645.  */
  646.  
  647.     if (((struct mtget *) arg)->mt_type < 256)
  648.         return(0);
  649.  
  650.     for (cnt = 0; cnt < rc; cnt += 2)
  651.     {
  652.         c = arg[cnt];
  653.         arg[cnt] = arg[cnt+1];
  654.         arg[cnt+1] = c;
  655.     }
  656.  
  657.     return(0);
  658.   }
  659. #endif /* RMTIOCTL */
  660. @
  661.  
  662.  
  663. 1.2
  664. log
  665. @Added support for long filenames and long symbolic linkes.
  666. @
  667. text
  668. @d23 1
  669. a23 1
  670. static char *RCSid = "$Header: /user2/rab/gnu-tar/RCS/rtape_lib.c,v 1.1 90/03/21 21:54:41 rab Exp Locker: rab $";
  671. d28 3
  672. d470 1
  673. a470 1
  674. unsigned int nbyte;
  675. @
  676.  
  677.  
  678. 1.1
  679. log
  680. @Initial revision
  681. @
  682. text
  683. @d23 1
  684. a23 1
  685. static char *RCSid = "$Header: /usr/src/local/usr.lib/librmt/RCS/rmtlib.c,v 1.7 89/03/23 14:09:51 root Exp Locker: root $";
  686. d27 4
  687. a30 1
  688.  * $Log:    rmtlib.c,v $
  689. d74 1
  690. a74 1
  691.  
  692. d82 1
  693. a82 1
  694. #define RMTIOCTL    1
  695. d150 1
  696. a150 1
  697.     pstat = signal(SIGPIPE, SIG_IGN);
  698. d512 1
  699. a512 1
  700.     pstat = signal(SIGPIPE, SIG_IGN);
  701. @
  702.